import { isTestNode, isElement } from './util.js'
import Watcher from './Watcher.js'

export default class Compile {
  constructor(vm, el) {
    this.$vm = vm
    this.$el = document.querySelector(el)
    this.compile(this.$el)
  }

  compile(el = document.getElementById('#app')) {

    const childNodes = el.childNodes

    Array.from(childNodes).forEach(node => {
      if (isTestNode(node)) {
        console.log(node)

        this.compileText(node)
      }


      if (isElement(node)) {
        const attrs = node.attributes
        Array.from(attrs).forEach(attr => {
          const key = attr.name
          const value = attr.value

          if (key.slice(0, 2) === 'v-') {
            this[key.slice(2)] && this[key.slice(2)](node, value)
          }
          if (key.slice(0, 1) === '@') {
            this.eventHeader(node, value)
          }

        })
      }
      const childNodes1 = node.childNodes
      if (childNodes1.length) {
        this.compile(node)
      }
    })

  }

  eventHeader(node, exp) {
    const event = this.$vm.$methods[exp]
    node.addEventListener(exp, event.bind(this.$vm))
  }

  compileText(node) {
    const r = RegExp.$1
    this.update(node, this.$vm, r, 'text')
  }

  text(node, exp) {
    this.update(node, this.$vm, exp, 'text')
  }

  show(node, exp) {
    this.update(node, this.$vm, exp, 'show')
  }


  html(node, exp) {
    this.update(node, this.$vm, exp, 'html')
  }

  update(node, vm, exp, dir) {

    const updateFn = this[dir + 'Updater']
    updateFn && updateFn(node, vm[exp]) // 初始化
    new Watcher(vm, exp, function (value) {
      updateFn && updateFn(node, value) // 初始化
    })

  }

  model(node, exp) {
    console.log(this.$vm)
    this.update(node, this.$vm, exp, 'model')
    node.addEventListener('input', e => {
      this.$vm[exp] = e.target.value
    })
  }


  modelUpdater(node, exp) {
    node.value = exp
  }

  showUpdater(node, exp) {
    if (!exp) {
      node.style.display = 'none'
    } else {
      node.style.display = 'block'
    }
  }

  htmlUpdater(node, exp) {
    node.innerHTML = exp
  }


  textUpdater(node, exp) {
    node.textContent = exp
  }
}